#include "TimeCorrelation.h"
#include <math.h>
#include <vector>

TimeCorrelation::TimeCorrelation(int t)
{
	timeCorr = new map<int, double>();
	time = t;
	timeSSD = 0;
}

TimeCorrelation::~TimeCorrelation(){
	delete timeCorr;
	list<ExtentStatistics*>::iterator it;
	for (it = timeSSD->begin(); it != timeSSD->end(); it++){
		delete (*it);
	}
	delete timeSSD;
}

// calculate correlation between this time and all other times
int TimeCorrelation::calcTimeCorrelation(int this_time, list<ExtentStatsAlgo*>* otherSSD){

	if (this_time == time){
		timeCorr->clear();
		copySSD(otherSSD);
		return 1;
	}
	else if (timeSSD != 0){
		int i, max;
		double w = 0;
		double sum1 = 0, sum2 = 0;
		int param = rand_rm;
		list<ExtentStatistics*>* t1 = timeSSD;
		list<ExtentStatsAlgo*>* t2 = otherSSD;

		if (t1->size() >= t2->size())
			max = t1->size();
		else 
			max = t2->size();

		vector<double> vec1 (max, 0);
		vector<double> vec2 (max, 0);


		// take 2 relevant vectors V1 V2
		list<ExtentStatistics*>::iterator it1 = t1->begin();
		list<ExtentStatsAlgo*>::iterator it2 = t2->begin();
		for(i=0; (it1 != t1->end() || it2 != t2->end()); i++)
		{
			if(it1 == t1->end()){
				vec1[i] = 0;
			}
			else{
				vec1[i] = (*it1)->getStat(param);	
				it1++;
			}

			if(it2 == t2->end()){
				vec2[i] = 0;
			}
			else{
				ExtentStatistics* stat = (*it2)->getStat(this_time);
				if (stat){
					vec2[i] = stat->getStat(param);
					it2++;
				}
				else {
					timeCorr->insert(pair<int, double>(this_time, -2.0));
					return 0;
				}
			}

			if(vec1[i]<0 || vec2[i]<0){
				timeCorr->insert(pair<int, double>(this_time, -2.0));
				return 0;
			}

			sum1 += vec1[i];
			sum2 += vec2[i];
		}

		// sub avg and sum the V1i^2 V2i^2
		double avg1 = (sum1/i) , avg2 = (sum2/i);
	
		sum1 = 0; sum2 = 0;
		for(int j=0; j<i; j++)
		{
			vec1[j] = vec1[j] - avg1;	
			vec2[j] = vec2[j] - avg2;
			sum1 += (vec1[j] * vec1[j]); 
			sum2 += (vec2[j] * vec2[j]);
		}

		//normalaize V1 V2 and mult vectors
		for(int j=0; j<i; j++)
		{
			if(sum1 && sum2){
				vec1[j] = vec1[j] / sqrt(sum1);
				vec2[j] = vec2[j] / sqrt(sum2);
			}
			w += vec1[j] * vec2[j];
		}

		timeCorr->insert(pair<int, double>(this_time, w));
	}
	return 0;
}

//copy SSD into timeSSD
void TimeCorrelation::copySSD(list<ExtentStatsAlgo*>* SSD){
	timeSSD = new list<ExtentStatistics*>();
	list<ExtentStatsAlgo*>::iterator it;
	for (it = SSD->begin(); it != SSD->end(); it++){
		ExtentStatistics* stats = new ExtentStatistics((*it)->getStat(time));
		timeSSD->push_back(stats);
	}
}